package me.sealer.ssm.controller;

import lombok.extern.slf4j.Slf4j;
import me.sealer.ssm.constant.Dict;
import me.sealer.ssm.constant.ErrorCodeConstant;
import me.sealer.ssm.constant.RoleConstant;
import me.sealer.ssm.constant.SsmConstant;
import me.sealer.ssm.exception.SsmException;
import me.sealer.ssm.model.Role;
import me.sealer.ssm.model.User;
import me.sealer.ssm.model.UserRole;
import me.sealer.ssm.service.RoleService;
import me.sealer.ssm.service.UserRoleService;
import me.sealer.ssm.service.UserService;
import me.sealer.ssm.utils.MessageConverterUtil;
import me.sealer.ssm.utils.StringUtil;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

import static me.sealer.ssm.constant.ErrorCodeConstant.SYSTEM_NOT_NULL;

/**
 * @author sealer
 * @date 2016/09/27
 */
@Slf4j
@Controller
@RequestMapping("/userRoleMgmt")
@RequiresRoles(value = {RoleConstant.ROLE_ADMIN})
public class UserRoleMgmtController {
    private final RoleService roleService;
    private final UserRoleService userRoleService;
    private final UserService userService;

    public UserRoleMgmtController(RoleService roleService, UserRoleService userRoleService, UserService userService) {
        this.roleService = roleService;
        this.userRoleService = userRoleService;
        this.userService = userService;
    }

    @RequestMapping("/modifyPre/{username}")
    public ModelAndView modifyPre(@PathVariable(value = Dict.USERNAME, required = false) String username, HttpServletRequest request) {
        if (StringUtil.isNullOrEmpty(username)) {
            String message = MessageConverterUtil.getMessage(request, Dict.USERNAME);
            throw new SsmException(SYSTEM_NOT_NULL, new Object[]{message});
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("userRoleModify");

        List<Role> havingRoles = roleService.getRolesByUsername(username);
        List<Integer> havingRolesIds = havingRoles.stream().map(role -> role.getId()).collect(Collectors.toList());

        List<Role> allRoles = roleService.getRoles();
        modelAndView.addObject(Dict.ALL_ROLES, allRoles);
        modelAndView.addObject(Dict.HAVING_ROLES_IDS, havingRolesIds);
        modelAndView.addObject(Dict.USERNAME, username);

        return modelAndView;
    }

    @RequestMapping("/modify")
    @Transactional(rollbackFor = Exception.class)
    public ModelAndView modify(@RequestParam(value = Dict.USERNAME, required = false) String username,
                               @RequestParam(value = Dict.ROLES, required = false) List<Integer> rolesIds, HttpServletRequest request) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("forward:modifyPre/" + username);

        if (StringUtil.isNullOrEmpty(username)) {
            String message = MessageConverterUtil.getMessage(request, Dict.USERNAME);
            throw new SsmException(SYSTEM_NOT_NULL, new Object[]{message});
        }

        if (rolesIds == null || rolesIds.size() == 0) {
            String message = MessageConverterUtil.getMessage(request, ErrorCodeConstant.ROLE_LIST_NULL);
            modelAndView.addObject(SsmConstant.RESULT_MESSAGE, message);
            return modelAndView;
        }

        User user = userService.findUserByUsername(username);
        if (user == null) {
            throw new SsmException(ErrorCodeConstant.USER_USER_NOT_EXISTS, new Object[]{username});
        }
        int userId = user.getId();
        userRoleService.deleteByUserId(userId);

        rolesIds.forEach(id -> {
            UserRole userRole = new UserRole(userId, id);
            userRoleService.insert(userRole);
        });

        String message = MessageConverterUtil.getMessage(request, ErrorCodeConstant.ROLE_MODIFY_SUCCESS);
        modelAndView.addObject(SsmConstant.RESULT_MESSAGE, message);
        return modelAndView;
    }
}
